package com.behome.socket_proxy.netty_D.client;

import com.behome.socket_proxy.netty_D.server.StandardDNettyServerHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class ProxyCilentHandler extends ChannelInboundHandlerAdapter {


    /**
     * 有客户端连接服务器会触发此函数
     *
     * @param ctx ctx
     * @return void
     * @author Ljy
     * @date 2021/3/10 15:00
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        //获取连接通道唯一标识
        ChannelId channelId = ctx.channel().id();
//        log.info("客户端【" + channelId + "】连接指令服务器[IP:" + clientIp + "--->PORT:" + insocket.getPort() + "]");
    }

    /**
     * 有客户端终止连接服务器会触发此函数
     *
     * @param ctx ctx
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ChannelId channelId = ctx.channel().id();
        quitServer(ctx);
//        log.info("客户端【" + channelId + "】退出指令服务器[IP:" + clientIp + "--->PORT:" + insocket.getPort() + "]");
    }

    /**
     * 有客户端发消息会触发此函数
     *
     * @param ctx 通道
     * @param msg 消息
     * @return void
     * @author Ljy
     * @date 2021/3/10 15:01
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        for (Map.Entry<Channel, NettyClient> channelNettyClientEntry : StandardDNettyServerHandler.getMap().entrySet()) {
            if (ctx.channel().equals(channelNettyClientEntry.getValue().getChannel())) {
                channelNettyClientEntry.getValue().clientCtx.writeAndFlush(msg);
            }
        }
        for (Map.Entry<Channel, NettyClient> channelNettyClientEntry : StandardDNettyServerHandler.getMap2().entrySet()) {
            if (ctx.channel().equals(channelNettyClientEntry.getValue().getChannel())) {
                channelNettyClientEntry.getValue().clientCtx.writeAndFlush(msg);
            }
        }
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        String socketString = ctx.channel().remoteAddress().toString();
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.debug("Server: " + socketString + " READER_IDLE 读超时");
            } else if (event.state() == IdleState.WRITER_IDLE) {
                log.debug("Server: " + socketString + " WRITER_IDLE 写超时");
                quitServer(ctx);
            } else if (event.state() == IdleState.ALL_IDLE) {
                log.debug("Server: " + socketString + " ALL_IDLE 总超时");
            }
        }
    }

    /**
     * 发生异常会触发此函数
     *
     * @param ctx   通道
     * @param cause cause
     * @return void
     * @author Ljy
     * @date 2021/3/10 15:02
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        ConcurrentHashMap<Channel, NettyClient> map = StandardDNettyServerHandler.getMap();
        ConcurrentHashMap<Channel, NettyClient> map2 = StandardDNettyServerHandler.getMap2();
        for (Map.Entry<Channel, NettyClient> channelNettyClientEntry : map.entrySet()) {
            if (ctx.channel().id().equals(channelNettyClientEntry.getValue().getChannel().id())) {
                StandardDNettyServerHandler.removeChannel(channelNettyClientEntry.getKey());
            }
            NettyClient nettyClient = map2.get(channelNettyClientEntry.getKey());
        }
        cause.printStackTrace();
    }

    public void quitServer(ChannelHandlerContext ctx) {
        int resultFlag = 2;
        Channel clientChannel = null;
        for (Map.Entry<Channel, NettyClient> channelNettyClientEntry : StandardDNettyServerHandler.getMap().entrySet()) {
            if (ctx.channel().equals(channelNettyClientEntry.getValue().getChannel())) {
                clientChannel = channelNettyClientEntry.getKey();
            }
        }
        for (Map.Entry<Channel, NettyClient> channelNettyClientEntry : StandardDNettyServerHandler.getMap2().entrySet()) {
            if (ctx.channel().equals(channelNettyClientEntry.getValue().getChannel())) {
                clientChannel = channelNettyClientEntry.getKey();
            }
        }
        if (clientChannel != null && clientChannel.isActive()) {
            NettyClient serverClient1 = StandardDNettyServerHandler.getMap().get(clientChannel);
            NettyClient serverClient2 = StandardDNettyServerHandler.getMap2().get(clientChannel);
            if (serverClient1 != null && serverClient1.getChannel() != null && !serverClient1.getChannel().isActive()) {
                resultFlag--;
                StandardDNettyServerHandler.getMap().remove(clientChannel);
            }
            if (serverClient2 != null && serverClient2.getChannel() != null && !serverClient2.getChannel().isActive()) {
                resultFlag--;
                StandardDNettyServerHandler.getMap2().remove(clientChannel);
            }
        } else {
            resultFlag = 0;
        }
        if (clientChannel != null && resultFlag == 0) {
            clientChannel.close();
        }
    }

}
